﻿using DataModels.Models.DHIS;
using DHISInteroperability.Resources;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ReportingManagement.Components.DHIS
{
    /// <summary>
    /// Interaction logic for DHISConfiguration.xaml
    /// </summary>
    public partial class DHISDatasetConfiguration : Window
    {
        private ReportDatasetLinkViewModel viewModel;

        public DHISDatasetConfiguration()
        {
            InitializeComponent();
            viewModel = new ReportDatasetLinkViewModel();
            viewModel.DatasetsElementLinks = new ObservableCollection<DatasetsLink>();
            gridDaataset.DataContext = viewModel;
        }

        private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var report = lstReports.SelectedItem as DataModels.Models.Report;
            if (report != null)
            {
                var datasetLinks = GenericTools.Utilities.GetReportDataSetLink(report.RepID);
                viewModel.ReportId = report.RepID;
                if (datasetLinks != null) viewModel.DatasetId = datasetLinks.DataSetId;
                
                viewModel.DatasetsElementLinks.Clear();
                for (int x = 0; x < report.ReportDataLocations.Count; x++)
                {
                    var i = report.ReportDataLocations[x];
                    // Here we will skip the first three data elements report 
                    // These are facility code, report year, month
                    if (i.DataPosition == 1) continue;  // Facility code
                    if (i.DataPosition == 2) continue;  // Month
                    if (i.DataPosition == 3) continue;  // Year

                    var link = new DatasetsLink();
                    link.ReportDataElement = i;
                    if (datasetLinks != null)
                    {
                        if (datasetLinks.ReportDataSetElementsLinks.Count > 0)
                        {
                            link.id = datasetLinks.ReportDataSetElementsLinks[x - 3].DataElementId;
                        }                        
                    }
                    viewModel.DatasetsElementLinks.Add(link);
                }
            }
        }

        private void cboDatasets_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var dataset = cboDatasets.SelectedItem as dataSet;
            if (dataset != null)
            {
                var dataBridge = new DHISDataBridge();
                dataset = dataBridge.GetDataSet(dataset.id, "dataElements[id,name]");
                dataGridCboDataElement.ItemsSource = dataset.dataElements;
            }
        }

        private void btnSave_Click(object sender, RoutedEventArgs e)
        {
            var report = lstReports.SelectedItem as DataModels.Models.Report;
            if (report != null)
            {
                var dataset = cboDatasets.SelectedItem as dataSet;
                if (dataset != null)
                {
                    var datasetLink = new ReportDataSetLink
                    {
                        ReportId = viewModel.ReportId,
                        DataSetId = viewModel.DatasetId
                    };

                    // Now set the report indicators and data elements
                    var elements = new List<ReportDataSetElementsLink>();
                    for (int index = 0; index < viewModel.DatasetsElementLinks.Count; index++)
                    {
                        var i = viewModel.DatasetsElementLinks[index];
                        // Check to make sure all dataset ids were filled correctly
                        if (string.IsNullOrWhiteSpace(i.id))
                        {
                            MessageBox.Show(this, 
                                string.Format("Indicator '{0}' is missing the corresponding data element in DHIS2", i.ReportDataElement.DataDescription), 
                                "DHIS Report Configuration", MessageBoxButton.OK, MessageBoxImage.Error);
                            SelectRowByIndex(dataGrid, index, 1);
                            return;
                        }

                        var element = new ReportDataSetElementsLink
                        {
                            ReportIndicatorId = i.ReportDataElement.MeasureNo,
                            DataElementId = i.id
                        };
                        elements.Add(element);
                    }
                    datasetLink.ReportDataSetElementsLinks = elements;                    

                    //btnReset.IsEnabled = false;
                    btnSave.IsEnabled = false;
                    try
                    {
                        bool saved = GenericTools.Utilities.SaveReportDataSetLink(datasetLink);
                        if (saved)
                        {
                            MessageBox.Show(this, "Report configuration was saved successfully",
                                "DHIS Report Configuration", MessageBoxButton.OK, MessageBoxImage.Information);
                        }
                        else
                        {
                            MessageBox.Show(this, "Operation did not complete", "DHIS Report Configuration",
                                MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(this, ex.Message, "DHIS Report Configuration",
                                MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                    finally
                    {
                        //btnReset.IsEnabled = true;
                        btnSave.IsEnabled = true;
                    }                    
                    
                }
            }
        }

        #region Static Method for DataGrid row and cell focusing
        public static DataGridCell GetCell(DataGrid dataGrid, DataGridRow rowContainer, int column)
        {
            if (rowContainer != null)
            {
                DataGridCellsPresenter presenter = FindVisualChild<DataGridCellsPresenter>(rowContainer);
                if (presenter == null)
                {
                    /* if the row has been virtualized away, call its ApplyTemplate() method
                     * to build its visual tree in order for the DataGridCellsPresenter
                     * and the DataGridCells to be created */
                    rowContainer.ApplyTemplate();
                    presenter = FindVisualChild<DataGridCellsPresenter>(rowContainer);
                }
                if (presenter != null)
                {
                    DataGridCell cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell;
                    if (cell == null)
                    {
                        /* bring the column into view
                         * in case it has been virtualized away */
                        dataGrid.ScrollIntoView(rowContainer, dataGrid.Columns[column]);
                        cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell;
                    }
                    return cell;
                }
            }
            return null;
        }

        public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is T)
                    return (T)child;
                else
                {
                    T childOfChild = FindVisualChild<T>(child);
                    if (childOfChild != null)
                        return childOfChild;
                }
            }
            return null;
        }

        public static void SelectRowByIndex(DataGrid dataGrid, int rowIndex, int cellIndex)
        {
            if (!dataGrid.SelectionUnit.Equals(DataGridSelectionUnit.FullRow))
                throw new ArgumentException("The SelectionUnit of the DataGrid must be set to FullRow.");

            if (rowIndex < 0 || rowIndex > (dataGrid.Items.Count - 1))
                throw new ArgumentException(string.Format("{0} is an invalid row index.", rowIndex));

            dataGrid.SelectedItems.Clear();
            /* set the SelectedItem property */
            object item = dataGrid.Items[rowIndex]; // = Product X
            dataGrid.SelectedItem = item;

            DataGridRow row = dataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex) as DataGridRow;
            if (row == null)
            {
                /* bring the data item (Product object) into view
                 * in case it has been virtualized away */
                dataGrid.ScrollIntoView(item);
                row = dataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex) as DataGridRow;
            }
            //TODO: Retrieve and focus a DataGridCell object
            if (row != null)
            {
                DataGridCell cell = GetCell(dataGrid, row, cellIndex);
                if (cell != null) cell.Focus();
            }
        }

        public static void SelectRowByIndex(DataGrid dataGrid, int rowIndex)
        {
            SelectRowByIndex(dataGrid, rowIndex, 0);
        }

        public static void SelectCellByIndex(DataGrid dataGrid, int rowIndex, int columnIndex)
        {
            if (!dataGrid.SelectionUnit.Equals(DataGridSelectionUnit.Cell))
                throw new ArgumentException("The SelectionUnit of the DataGrid must be set to Cell.");

            if (rowIndex < 0 || rowIndex > (dataGrid.Items.Count - 1))
                throw new ArgumentException(string.Format("{0} is an invalid row index.", rowIndex));

            if (columnIndex < 0 || columnIndex > (dataGrid.Columns.Count - 1))
                throw new ArgumentException(string.Format("{0} is an invalid column index.", columnIndex));

            dataGrid.SelectedCells.Clear();

            object item = dataGrid.Items[rowIndex]; //=Product X
            DataGridRow row = dataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex) as DataGridRow;
            if (row == null)
            {
                dataGrid.ScrollIntoView(item);
                row = dataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex) as DataGridRow;
            }
            if (row != null)
            {
                DataGridCell cell = GetCell(dataGrid, row, columnIndex);
                if (cell != null)
                {
                    DataGridCellInfo dataGridCellInfo = new DataGridCellInfo(cell);
                    dataGrid.SelectedCells.Add(dataGridCellInfo);
                    cell.Focus();
                }
            }
        }
        #endregion

        private void btnReset_Click(object sender, RoutedEventArgs e)
        {
            ListBox_SelectionChanged(null, null);
        }
    }
}
